본문으로 건너뛰기

useInsertionEffect

🧑🏻‍💻 useInsertionEffect


useInsertionEffectuseEffect의 버전 중 하나로, DOM 변이 전에 실행된다. (DOM 변이 전에 스타일을 주입한다.)

✅ useInsertionEffect 문법

useInsertionEffect(setup, dependencies?)
  • setup는 Effect의 로직이 포함된 함수이다. 셋업 함수는 클린업 함수를 선택적으로 반환할 수도 있다.
  • dependenciessetup 코드 내에서 참조된 모든 반응형 값의 목록이다. 반응형 값에는 props, state, 컴포넌트 본문 내부에서 직접 선언된 모든 변수와 함수가 포함된다.
  • undefined를 반환한다.

🧑🏻‍💻 알고 가기


✅ 주의 사항

  • useInsertionEffect는 CSS-in-JS 라이브러리 작성자를 위한 훅이다.

  • CSS-in-JS 라이브러리에서 작업 중, 런타임에 <style> 태그를 주입하는 경우가 아니라면, useEffectuseLayoutEffect가 더 나을 수 있다.

  • Effect는 클라이언트에서만 실행된다. 서버 렌더링 중에는 실행되지 않는다. (useEffect와 마찬가지로 useInsertionEffect는 서버에서 실행되지 않는다.)

  • useInsertionEffect가 실행될 때까지는 DOM이 아직 업데이트되지 않은 상태이기 때문에 refs가 아직 첨부되지 않은 상태이다.

  • useInsertionEffect 내부에서는 state를 업데이트할 수 없다.

🧑🏻‍💻 활용 및 생각할 거리


✅ useInsertionEffect를 사용하는 경우

// Inside your CSS-in-JS library
// CSS-in-JS 라이브러리 코드 내부에
let isInserted = new Set();
function useCSS(rule) {
useInsertionEffect(() => {
// As explained earlier, we don't recommend runtime injection of <style> tags.
// 앞서 설명한 것처럼 <style> 태그의 런타임 주입은 권장하지 않습니다.
// But if you have to do it, then it's important to do in useInsertionEffect.
// 하지만 런타임 주입을 해야한다면, useInsertionEffect에서 수행하는 것이 중요합니다.
if (!isInserted.has(rule)) {
isInserted.add(rule);
document.head.appendChild(getStyleForRule(rule));
}
});
return rule;
}

function Button() {
const className = useCSS('...');
return <div className={className} />;
}
  • 런타임 주입이 React 라이프 사이클에서 잘못된 시점이 발생할 때
  • DOM 변경 전에 스타일을 주입할 때

✅ CSS-in-JS 라이브러리에서 동적 스타일 삽입하기

  • 3가지 접근 방식
  1. 컴파일러를 사용하여 CSS 파일로 정적 추출
  2. 인라인 스타일. ex) <div style={{ opacity: 1 }}>
  3. 런타임에 <style> 태그 삽입

✅ 런타임 환경에서 <style> 태그 주입을 권장하지 않는 이유

  1. 브라우저에서 스타일을 훨씬 더 자주 다시 계산하도록 하기 때문이다.
  2. 런타임 주입이 React 라이프 사이클에서 잘못된 시점에 발생하면 속도가 매우 느려질 수 있다.
  • 2번의 경우 useInsertionEffect 를 활용하여 해결 가능하지만 React에서는 가급적 아래 방식들을 더 권장한다.
  1. 컴파일러를 사용하여 CSS 파일로 정적 추출하기.
  2. 인라인 스타일 사용하기.
    • 예: <div style={{ opacity: 1 }}>